package fr.lelouet.ga.reducers.evaluators;

import java.util.HashMap;

import fr.lelouet.ga.reducers.Evaluator;

/**
 * An evaluator that only caches previous answers and delegates unanswered
 * requests to another evaluator<br />
 * Useful when computing a value is long and T does not memorizes its value and
 * it the same value may be computed several times.<br />
 * However, this uses much ram and should be cleared from time to time, at least
 * partially.<br />
 * A better way would be to add valuation memory in the T evaluated, but that
 * may not ever be possible.
 * @author le louet
 * @param <T>
 */
public class CachingEvaluator<T> extends HashMap<T, Double> implements
    Evaluator<T> {

  private static final long serialVersionUID = 1L;

  protected Evaluator<T> cached;

  /**
   * changes the evaluator that is cached. That clears the map, since it has no
   * more meaning
   */
  protected void setCached(Evaluator<T> toCache) {
    cached = toCache;
    clear();
  }

  public CachingEvaluator(Evaluator<T> toCache) {
    setCached(toCache);
  }

  /**
   * creates a cachingEvaluator on a given evaluator and with a base size for
   * the map<br />
   * Useful when you know the minimum number of elements your map is supposed to
   * manipulate
   */
  public CachingEvaluator(Evaluator<T> toCache, int size) {
    super(size);
    setCached(toCache);
  }

  @Override
  public double eval(T target) {
    if (!containsKey(target)) {
      put(target, cached.eval(target));
    }
    return get(target);
  }

}
